Skip to content

Add a "Conversation width" setting (Comfortable / Wide / Full) to Appearance#63

Merged
DragonnZhang merged 2 commits into
mainfrom
loop/conversation-width
Jul 19, 2026
Merged

Add a "Conversation width" setting (Comfortable / Wide / Full) to Appearance#63
DragonnZhang merged 2 commits into
mainfrom
loop/conversation-width

Conversation

@DragonnZhang

Copy link
Copy Markdown
Collaborator

Closes #62

What & why

OpenWork rendered the chat transcript and the composer inside a single fixed
reading column — CHAT_LAYOUT.maxWidth = max-w-[840px] — with no way to change
it. On large/ultrawide displays that wastes most of the window, and code-heavy
conversations (wide diffs, long tool output, tables) get needlessly wrapped.

Comparable desktop clients all expose this: Claude Desktop (wider chat),
ChatGPT desktop (chat width), Codex / VS Code (content width). This adds
the same affordance to OpenWork's Appearance page.

Changes

  • context/ConversationWidthContext.tsx — new renderer-only preference
    (comfortable | wide | full), persisted in localStorage
    (craft-conversation-width), mirroring the merged ReduceMotionContext
    (Add a "Reduce motion" accessibility setting to Appearance #51). It reflects the choice onto <html> as data-conversation-width and
    drives a CSS custom property --chat-content-max-width (840px / 1100px /
    none).
  • ChatDisplay.tsx / ChatInputZone.tsx — the transcript container and the
    composer now read max-width: var(--chat-content-max-width, 840px). The
    840px fallback means the shared web viewer (packages/ui) and
    compact/popover embeddings are untouched.
  • AppearanceSettingsPage.tsx — a segmented control in the Interface
    section, right below "Reduce motion".
  • SettingsSegmentedControl.tsx — small, backward-compatible testId prop
    (group + per-option data-testid) for e2e targeting.
  • local-storage.ts — new conversationWidth key.
  • i18n — 5 new keys across all 7 locales (en, zh-Hans, de, es, ja,
    hu, pl).

Frontend-only — no qwen-code backend change.

Verification (DoD)

  • bun run typecheck:all — my files clean; zero-delta vs main (identical
    pre-existing error set).
  • bun testzero-delta vs main (56-failure baseline set byte-identical;
    i18n locale-parity outcomes unchanged).
  • bun run electron:build:renderer — ✅ builds (all changed code is renderer +
    locales).
  • CDP assertion e2e/assertions/conversation-width.assert.ts — drives the real
    Settings → Appearance UI, cycles all three options, and asserts for each: the
    radio aria-checked state, the data-conversation-width attribute on <html>,
    the computed --chat-content-max-width CSS variable (840px/1100px/none),
    and the persisted localStorage value — proving it applies and reverts.

Environment note: the CDP assertion could not be executed in this
sandbox
— outbound egress returns 403 for the Electron binary download and
for the libsignal-node / whiskeysockets/eslint-config git-tarball deps, so
electron:build:main, the full bun run build lint step, and launching Electron
all fail before the app starts. These are pre-existing environment blockers
(the same egress limit recorded for the merged #51), not regressions from this
change. The assertion mirrors the merged reduce-motion assertion's exact CDP API
and is ready to run in CI where the Electron binary is available.


Generated by Claude Code

@DragonnZhang DragonnZhang added enhancement New feature or request loop-bot labels Jul 6, 2026
DragonnZhang pushed a commit that referenced this pull request Jul 19, 2026
Resolve merge conflicts with main:
- ChatDisplay.tsx: combine main's chat-transcript ScrollArea test id (used by
  the scroll-to-bottom e2e) with this PR's configurable --chat-content-max-width
  messages container.
- docs/loop/feature-ledger.md: adopt main's canonical ledger and prepend this
  PR's conversation-width (#63) row.
claude added 2 commits July 20, 2026 00:55
…earance

Adds a renderer-only "Conversation width" preference to Settings →
Appearance → Interface, letting users widen the chat transcript and
composer beyond the fixed 840px reading column — matching the width
controls in Claude Desktop, ChatGPT desktop and Codex / VS Code.

- New ConversationWidthProvider (localStorage `craft-conversation-width`,
  mirroring ReduceMotionContext) reflects the choice onto `<html>` as
  `data-conversation-width` and drives a `--chat-content-max-width` CSS
  variable (840px / 1100px / none).
- ChatDisplay transcript container and ChatInputZone read the variable via
  `max-width: var(--chat-content-max-width, 840px)`; the fallback leaves the
  shared web viewer unchanged and compact/popover embeddings untouched.
- Segmented control in the Appearance Interface section; adds an optional
  `testId` to SettingsSegmentedControl for e2e targeting.
- 5 new i18n keys across all 7 locales.
- CDP assertion drives the real Settings UI, cycling all three options and
  asserting the radio state, `<html>` attribute, computed CSS variable and
  persisted localStorage value.

Closes #62
@DragonnZhang
DragonnZhang force-pushed the loop/conversation-width branch from 2bd2908 to c4ad5bf Compare July 19, 2026 16:57
@DragonnZhang
DragonnZhang merged commit 2bb5bc0 into main Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request loop-bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a "Conversation width" setting (Comfortable / Wide / Full) to Appearance

2 participants